home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / DEV / A-B / Anim Cursor.cpt / CursorCtl.c < prev   
Text File  |  1990-01-24  |  9KB  |  325 lines

  1. /************************************************************************/
  2. /*                                                                        */
  3. /*    Cursor Control routines                                                */
  4. /*                                                                        */
  5. /*        -- THINK C (V 4.0) version by Eric H. Seale, 1/23/90            */
  6. /*                                                                        */
  7. /*           Based on Lightspeed Pascal code by Chris Reed of San Angelo,    */
  8. /*           TX, and Yasser Farra of Austin, TX                            */
  9. /*                                                                        */
  10. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  11. /*                                                                        */
  12. /* CREDITS:                                                                */
  13. /*                                                                        */
  14. /*        Chris Reed -- original idea, simple implementation                */
  15. /*                                                                        */
  16. /*        Yasser Farra -- improved exception handling, remove use of         */
  17. /*                buggy "SetUpA5" & "RestoreA5" routines (see tech note    */
  18. /*                208), animation speed and "acur" resource ID are now    */
  19. /*                parameters                                                */
  20. /*                                                                        */
  21. /*        Eric Seale    -- translate to THINK C (from Lightspeed Pascal),     */
  22. /*                "flesh out" the documentation                            */
  23. /*                                                                        */
  24. /************************************************************************/
  25. #include <VRetraceMgr.h>
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32. /************************************************************************/
  33. /*                                                                        */
  34. /*    Define some new data types to handle the cursor frames                */
  35. /*                                                                        */
  36. /************************************************************************/
  37. typedef struct    {
  38.     int            frameCount;    /* number of frames in animation sequence */
  39.     int            whichFrame;    /* current frame number */
  40.     CursHandle    frame[];    /* list of "CURS" resources */
  41.     }    acur;
  42.  
  43. typedef    acur    *acurPtr;
  44. typedef acurPtr    *acurHandle;
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52. /************************************************************************/
  53. /*                                                                        */
  54. /*    Define some "global" variables for our use                            */
  55. /*                                                                        */
  56. /************************************************************************/
  57. acurHandle    frameList;                /* handle to "acur" resource */
  58. VBLTask        cursVBL;                /* VBL task to handle cursor animation */
  59. Boolean        cursAnimationEnabled,    /* able to load "acur" and "CURS" rsrc's */
  60.             cursAlreadyOn;            /* cursor animation already running */
  61. int            cursSpeed;                /* # ticks between consec. frames */
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70. /************************************************************************/
  71. /*                                                                        */
  72. /*    Function Prototypes for our code here                                */
  73. /*                                                                        */
  74. /************************************************************************/
  75.  
  76. pascal long NuSetUpA5(void);
  77.  
  78. pascal long NuRestoreA5(long);
  79.  
  80. SetWatchCursor(void);
  81.  
  82. InitCursAnimation (int);
  83.  
  84. CursorAnimationVBL(void);
  85.  
  86. AnimateCursor (int);
  87.  
  88. StopCursor(void);
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96. pascal long NuSetUpA5(void)
  97. /************************************************************************/
  98. /*                                                                        */
  99. /*    pascal long NuSetUpA5(void)                                            */
  100. /*        -- This routine sets up the A5 to point to the boundary         */
  101. /*           between the application globals and the application             */
  102. /*           parameters. It returns the previous value of A5. This         */
  103. /*           function is used instead of SetUpA5 which is dangerous as it    */
  104. /*           does not return the old value of A5 but rather leaves it on    */
  105. /*           the stack--see tech note #208 for more details                */
  106. /*                                                                        */
  107. /*    Note that both the Tech Note and Yasser's Pascal code called this    */
  108. /*    routine "SetCurrentA5" -- it seemed that since this replaces the    */
  109. /*    routine "SetUpA5," a more "intuitively obvious" name could be used    */
  110. /*    (makes life easier for those used to the old names).  Also, note     */
  111. /*    that the assembler "equivalents" for the inline code are from         */
  112. /*    Apple's Tech Note -- I'm no assembly language whiz, so I can't        */
  113. /*    vouch for its accuracy (I just know that the hex works fine).        */
  114. /*                                                                        */
  115. /************************************************************************/
  116.      =      {    
  117.          0x2E8D,     /* move.l    a5, 4(a7)        */
  118.          0x2A78,     /* move.l    currentA5, a5    */
  119.          0x0904         /* rts                        */
  120.          };
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127. pascal long NuRestoreA5(long newA5)
  128. /************************************************************************/
  129. /*                                                                        */
  130. /*    pascal long NuRestoreA5(long)                                        */
  131. /*        -- This routine sets the value of A5 to "newA5". It should be    */
  132. /*           used to restore the old value of A5 at the end of a             */
  133. /*           completion routine or a VBL task. It also returns the         */
  134. /*           previous value of A5. This function is used instead of         */
  135. /*           RestoreA5 which assumes the old value of A5 is still on the     */
  136. /*           stack--see tech note #208 for more details                    */
  137. /*                                                                        */
  138. /*    Note that both the Tech Note and Yasser's Pascal code called this    */
  139. /*    routine "SetA5" -- change the name back if you'd like.                */
  140. /*                                                                        */
  141. /************************************************************************/
  142.     = {    
  143.         0x2F4D,     /* move.l    (a7)+a0        */
  144.         0x0004,     /* move.l    a5, 4(a7)    */
  145.         0x2A5F        /* move.l    (a7)+, a5    */
  146.         };            /* jmp.l    (a0)        */
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156. SetWatchCursor()
  157. /************************************************************************/
  158. /*                                                                        */
  159. /*    SetWatchCursor(void)                                                */
  160. /*        -- set cursor to standard "watch" (cursor animation is disabled)*/
  161. /*                                                                        */
  162. /************************************************************************/
  163. {
  164. CursHandle    myCursor;
  165.  
  166.     myCursor = GetCursor(watchCursor);
  167.     SetCursor(*myCursor);
  168. }
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177. InitCursAnimation(acurID)
  178. int        acurID;                            /* RSRC ID of "acur" resource    */
  179. /************************************************************************/
  180. /*                                                                        */
  181. /*    InitCursAnimation(int)                                                */
  182. /*        -- This procedure tries to load the "acur" resource and if        */
  183. /*           found tries to load all the "CURS" resources listed in the    */
  184. /*           "acur" resource                                                */
  185. /*                                                                        */
  186. /************************************************************************/
  187. {
  188. int        i, 
  189.         errorCode;
  190.  
  191.     /* Get the "acur" resource */
  192.     frameList = (acurHandle)GetResource('acur', acurID);
  193.     errorCode = ResError();
  194.  
  195.     if (frameList == 0L)    errorCode = resNotFound;
  196.  
  197.     if (errorCode == noErr)    {
  198.         i = 0;
  199.         
  200.         while ((i < (**frameList).frameCount) && (errorCode == noErr)){
  201.             /* Get the "CURS" resources whose ID's are in the high word */
  202.             /* of the frame field.  Store handle to these resources in     */
  203.             /* the same frame field */
  204.                 (**frameList).frame[i] = 
  205.                     GetCursor( HiWord((long)((**frameList).frame[i])) );
  206.                 errorCode = ResError();
  207.                 if ((**frameList).frame[i] == 0L)    
  208.                     errorCode |= resNotFound;
  209.                 i++;
  210.             }
  211.         
  212.         (**frameList).whichFrame = 1;    /* Set initial frame */
  213.         }
  214.  
  215.     cursAnimationEnabled = (errorCode == noErr);/* True if no error found */
  216. }
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225. CursorAnimationVBL()
  226. /************************************************************************/
  227. /*                                                                        */
  228. /*    CursorAnimationVBL(void)                                            */
  229. /*        -- VBL routine to set the cursor to the next cursor in the         */
  230. /*           animation sequence                                            */
  231. /*                                                                        */
  232. /************************************************************************/
  233. {
  234. long    oldA5;
  235.  
  236.         oldA5 = NuSetUpA5();
  237.  
  238.         /* frameList and all frame handles are assumed to be locked */
  239.         SetCursor(*((**frameList).frame[(**frameList).whichFrame]));
  240.  
  241.         if (++(**frameList).whichFrame >= (**frameList).frameCount)
  242.             (**frameList).whichFrame = 1;
  243.  
  244.         cursVBL.vblCount = cursSpeed;    /* Reinstall the VBL */
  245.  
  246.         oldA5 = NuRestoreA5(oldA5);
  247. }
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255. AnimateCursor(speed)
  256. int        speed;                        /* Ticks between consecutive frames */
  257. /************************************************************************/
  258. /*                                                                        */
  259. /*    AnimateCursor(int)                                                    */
  260. /*        -- Install our task in the vertical retrace queue unless cursor    */
  261. /*           animation is not enabled then use watch cursor                */
  262. /*                                                                        */
  263. /************************************************************************/
  264. {
  265. int        errorcode, i;
  266.  
  267.     if (!cursAlreadyOn) {
  268.         cursAlreadyOn = TRUE;
  269.  
  270.         if (cursAnimationEnabled) {
  271.             /* Lock all handles that will be accessed from the VBL */
  272.             HLock((Handle)(frameList));
  273.             for (i=0; i<(**frameList).frameCount; i++)
  274.                 HLock((Handle)((**frameList).frame[i]));
  275.  
  276.             (**frameList).whichFrame = 1; /* Set initial frame */
  277.  
  278.             /* Set up the VBL task fields and install it */
  279.             cursVBL.qType = vType;
  280.             cursVBL.vblAddr = &CursorAnimationVBL;
  281.             cursVBL.vblCount = speed; /* next VBL after "speed" ticks */
  282.             cursVBL.vblPhase = 0;
  283.  
  284.             errorcode = VInstall(&cursVBL);
  285.  
  286.             cursSpeed = speed;    /* Set the speed of animation */
  287.             }
  288.         else    /* Use watch cursor */
  289.                 SetWatchCursor();
  290.         }
  291. }
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299. StopCursor()
  300. /************************************************************************/
  301. /*                                                                        */
  302. /*    StopCursor(void)                                                    */
  303. /*        -- Remove the VBL task from the vertical retrace queue and         */
  304. /*           restore the arrow cursor                                        */
  305. /*                                                                        */
  306. /************************************************************************/
  307. {
  308. int        errorCode, i;
  309.  
  310.     if (cursAlreadyOn) {
  311.         cursAlreadyOn = FALSE;
  312.  
  313.         if (cursAnimationEnabled) {
  314.             errorCode = VRemove(&cursVBL);
  315.  
  316.             /* Unlock all handles that were locked before VBL */
  317.             /* installation */
  318.             HUnlock((Handle)(frameList));
  319.             for (i = 0; i< (**frameList).frameCount; i++)
  320.                 HUnlock((Handle)((**frameList).frame[i]));
  321.             }
  322.  
  323.         InitCursor();
  324.         }
  325. }